<?php
// +----------------------------------------------------------------------
// | View 视图服务
// +----------------------------------------------------------------------
// | * 视图层
// | * 1.查询所有关联表的字段
// | * 2.处理字段（可显示、可编辑、可排序、可分组、可过滤）、还要通过临时字段、字段权限进行判断，组装出view需要的字段
// | * 3.组装view视图的表格列
// +----------------------------------------------------------------------
// | 错误编码头 231xxx
// +----------------------------------------------------------------------

namespace common\service;

use common\exception\LogicException;
use common\model\StatusModel;
use common\model\StageModel;
use common\model\StepCategoryModel;
use common\model\TemplateTodoModel;
use common\model\UserModel;
use common\validate\Stage;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;


class StageService
{
    use SingletonTrait;

    private $stageModel;

    function __construct()
    {
        $this->stageModel = model(StageModel::class);
    }

    /**
     * 添加/更新 阶段
     * @param $data
     * @return bool|float|int|string
     * @throws \Exception
     */
    public function save($data)
    {
        $data['upstream_delivery_step_category_id'] = json_encode($data['upstream_delivery_step_category_id'] ?? []);

        $stageSavedList = $this->stageModel->field('order_number, name, id')->select();
        $stageSavedName = array_combine(array_column($stageSavedList, 'name'), array_column($stageSavedList, 'id'));
        $stageIds = array_column($stageSavedList, 'id');

        if (isset($data['id'])) {
            if (!in_array($data['id'], $stageIds)) {
                throw new LogicException('stage not found', ErrorCode::STAGE_NOT_FOUND);
            }
//            if (isset($stageSavedOrder[$data['order_number']]) && ($stageSavedOrder[$data['order_number']] != $data['id'])) {
//                throw new LogicException('stage order number in use', ErrorCode::STAGE_ORDER_NUMBER_IN_USE);
//            }
            if (isset($stageSavedName[$data['name']]) && ($stageSavedName[$data['name']] != $data['id'])) {
                throw new LogicException('stage name in use', ErrorCode::STAGE_NAME_IN_USE);
            }
            $data = array_merge($data, [
                'tenant_id' => auto_fill_tenant_id(),
                'updated_by' => fill_created_by(),
                'updated' => time()
            ]);
            return $this->stageModel->modifyItem($data);
        } else {
//            if (isset($stageSavedOrder[$data['order_number']])) {
//                throw new LogicException('stage order number in use', ErrorCode::STAGE_ORDER_NUMBER_IN_USE);
//            }
            if (isset($stageSavedName[$data['name']])) {
                throw new LogicException('stage name in use', ErrorCode::STAGE_NAME_IN_USE);
            }
            $data = array_merge($data, [
                'tenant_id' => auto_fill_tenant_id(),
                'created_by' => fill_created_by()
            ]);
            return $this->stageModel->addItem($data);
        }
    }

    /**
     * 移除阶段
     * @param $param
     * @return false|float|int|mixed|string
     */
    public function remove($param)
    {
        $stageIdList = $param['stage_id_list'] ?? [];
        if (empty($stageIdList)) {
            return -1;
        }
        return $this->stageModel->where(['id' => ['IN', $stageIdList]])->delete();
    }

    /**
     * 阶段列表
     * @return array
     * @throws \Exception
     */
    public function list($param)
    {
        $filter = $param['filter'] ?? [];
        $order = $param['order'] ?? "order_number ASC";
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $data['total'] = 0;
        $data['rows'] = [];

        $data['total'] = count($this->stageModel
            ->field('id')
            ->where($filter)
            ->select());

        $stageList = $this->stageModel
            ->field('id,name,type,step_category_id,order_number,ratio_list,delivery_note_type,upstream_delivery_step_category_id,json')
            ->where($filter)
            ->page($page[0], $page[1])
            ->order($order)
            ->select();

        foreach ($stageList as &$item) {
            $item = $this->formatStage($item);
        }

        $data['rows'] = $stageList;
        return $data;
    }

    /**
     * 获取阶段列表
     * @param $filter
     * @return array|false
     */
    public function getStageListLite($filter)
    {
        $stageList = model(StageModel::class)->where($filter)->field('id, name, type, step_category_id, ratio_list')->select();
        foreach ($stageList as &$item) {
            $item = $this->formatStage($item);
        }
        return array_combine(array_column($stageList, 'id'), $stageList);
    }

    /**
     * 查询单条阶段
     * @param $id
     * @return array|mixed
     * @throws \Exception
     */
    public function getOne($id)
    {
        $getOne = array_shift($this->list(['filter' => ['id' => $id], 'fields' => 'id,name,type,step_category_id,ratio_list'])['rows']);

        $getOne = $this->formatStage($getOne);
        return $getOne;
    }

    /**
     * 格式化阶段
     * @param $stage
     * @return mixed
     */
    private function formatStage($stage)
    {
        if (empty($stage)) {
            return [];
        }
        $stage['upstream_delivery_step_category_id'] = json_decode($stage['upstream_delivery_step_category_id'] ?? '{}', true);
        $stage['json'] = json_decode($stage['json'] ?? '{}', true);

        if ($stage['type'] == 'standard_review') {
            $stage['ratio_list'] = json_decode($stage['ratio_list'], true);
            $columnInteger = [
                'days',
                'order_number',
                'add_percentage',
                'edit_percentage',
            ];
            foreach ($stage['ratio_list'] as &$ratio) {
                foreach ($ratio as $key => &$item) {
                    if (in_array($key, $columnInteger)) {
                        $item = intval($item);
                    } else {
                        if (is_array($item)) {
                            $item = implode(',', $item);
                        }
                    }
                }
            }
        } else {
            unset($stage['ratio_list']);
        }
        return $stage;
    }

    /**
     * 阶段排序
     * 1. 关联环节show_index顺序
     * 2. 阶段内字段order_number
     * @return array|false|mixed|string
     */
    public function getStageOrderList($filter, $tenantId)
    {
        $stageId = model(TemplateTodoModel::class)
            ->join('project_relation_template_todo on project_relation_template_todo.template_todo_id = template_todo.id')
            ->where($filter)
            ->field("template_todo.stage_id")
            ->column("stage_id");

        $stageId = array_unique($stageId);
        $stageId = array_filter($stageId, function ($item) {
            return !empty($item);
        });
        if (empty($stageId)) {
            return [];
        }

        $stageList = model(StageModel::class)
            ->where(['id' => ['IN', $stageId]])
            ->field('id,type,name,order_number,step_category_id,delivery_note_type,upstream_delivery_step_category_id')
            ->select();

        $stepCategoryList = model(StepCategoryModel::class)->field('id, show_index')->select();
        array_walk($stageList, function (&$item) use ($stepCategoryList) {
            $stageStepCategoryId = explode(',', $item['step_category_id']);

            foreach ($stageStepCategoryId as &$id) {
                $id = intval($id);
            }

            $stepCategoryBind = array_filter($stepCategoryList, function ($item) use ($stageStepCategoryId) {
                return in_array($item['id'], $stageStepCategoryId);
            });
            $showIndexList = array_column($stepCategoryBind, 'show_index');

            sort($showIndexList);
            $item['step_category_show_id'] = array_shift($showIndexList);
        });

        usort($stageList, function ($a, $b) {
            if ($a['step_category_show_id'] > $b['step_category_show_id']) {
                return 1;
            }
            if ($a['step_category_show_id'] < $b['step_category_show_id']) {
                return -1;
            }
            if ($a['order_number'] >= $b['order_number']) {
                return 1;
            }
            return -1;
        });

        return $stageList;
    }
}


